package com.ybf.user.dal;

import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.cglib.core.Converter;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;

/**
 * @author poyangchen
 */
public class BeanUtils implements Serializable {
    private static final transient long serialVersionUID = 1L;
    private static ConcurrentMap<String, BeanCopier> beanCopiers = new ConcurrentHashMap();

    public BeanUtils() {
    }


    public static <A, B> List<B> copyListTo(List<A> sources, Class<B> clz) {
        try {
            if (sources == null) {
                return null;
            } else {
                ArrayList var9 = new ArrayList();
                if (sources.size() == 0) {
                    return var9;
                } else {
                    Object val = sources.get(0);
                    String key = clz.getName() + ":" + val.getClass().getName();
                    BeanCopier copier = null;
                    if (beanCopiers.containsKey(key)) {
                        copier = (BeanCopier) beanCopiers.get(key);
                    } else {
                        copier = BeanCopier.create(val.getClass(), clz, false);
                        beanCopiers.putIfAbsent(key, copier);
                    }

                    Iterator var6 = sources.iterator();

                    while (var6.hasNext()) {
                        Object a = var6.next();
                        Object clone = clz.newInstance();
                        copier.copy(a, clone, (Converter) null);
                        var9.add(clone);
                    }

                    return var9;
                }
            }
        } catch (Exception var91) {
            throw new RuntimeException(var91);
        }
    }

    /**
     * 属性copy
     *
     * @author 向南
     * @date 11:08 2023/5/18
     * @param: source
     * @param: target
     **/
    public static void copyProperties(Object source, Object target) {
        org.springframework.beans.BeanUtils.copyProperties(source, target, getNullPropertyNames(source));
    }

    private static String[] getNullPropertyNames(Object source) {
        BeanWrapper beanWrapper = new BeanWrapperImpl(source);
        PropertyDescriptor[] propertyDescriptors = beanWrapper.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<>();
        for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
            Object propertyValue = beanWrapper.getPropertyValue(propertyDescriptor.getName());
            if (Objects.isNull(propertyValue)) {
                emptyNames.add(propertyDescriptor.getName());
            }
        }
        return emptyNames.toArray(new String[emptyNames.size()]);
    }

    public static <T> T copyBean(Object source, Class<T> clz) {
        try {
            if (Objects.isNull(source)) {
                return null;
            }
            Object var5 = clz.newInstance();
            String key = clz.getName() + ":" + source.getClass().getName();
            BeanCopier copier = null;
            if (beanCopiers.containsKey(key)) {
                copier = (BeanCopier) beanCopiers.get(key);
            } else {
                copier = BeanCopier.create(source.getClass(), clz, false);
                beanCopiers.putIfAbsent(key, copier);
            }

            copier.copy(source, var5, (Converter) null);
            return (T) var5;
        } catch (Exception var51) {
            var51.printStackTrace();
            throw new RuntimeException(var51);
        }
    }

    /**
     * BeanMerge，对象属性合并
     * 将sourceBean非空属性合并至target
     *
     * @Author qingyun
     */
    public static <M> void beanMerge(M target, M sourceBean) {
        try {
            //获取目标bean
            BeanInfo beanInfo = Introspector.getBeanInfo(target.getClass());
            // 遍历所有属性
            for (PropertyDescriptor descriptor : beanInfo.getPropertyDescriptors()) {
                // 如果是可写属性
                if (descriptor.getWriteMethod() != null) {
                    Object defaultValue = descriptor.getReadMethod().invoke(sourceBean);
                    //可以使用StringUtil.isNotEmpty(defaultValue)来判断
                    if (defaultValue != null && !"".equals(defaultValue)) {
                        //用非空的defaultValue值覆盖到target去
                        descriptor.getWriteMethod().invoke(target, defaultValue);
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> Map<String, Object> beanToMap(T bean) {
        Map<String, Object> map = new HashMap<>();
        if (bean != null) {
            BeanMap beanMap = BeanMap.create(bean);
            for (Object key : beanMap.keySet()) {
                map.put(key + "", beanMap.get(key));
            }
        }
        return map;
    }


//    public static <T> Map<String, String> toStringMap(T bean) {
//        Map<String, String> map = Maps.newHashMap();
//        if (bean != null) {
//            BeanMap beanMap = BeanMap.create(bean);
//            for (Object key : beanMap.keySet()) {
//                map.put(key + "", beanMap.get(key) + "");
//            }
//        }
//        return map;
//    }

    /**
     * map转换成bean
     *
     * @param map
     * @param class1
     * @param <T>
     * @return
     */
    public static <T> T mapToBean(Map<String, Object> map, Class<T> class1) {
        T bean = null;
        try {
            bean = class1.newInstance();
            org.apache.commons.beanutils.BeanUtils.populate(bean, map);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return bean;
    }

    /**
     * 将List中的Map转换成Bean列表
     *
     * @param list  包含属性值的Map列表
     * @param clazz 目标Bean的Class
     * @param <T>   泛型类型
     * @return 转换后的Bean列表
     */
    public static <T> List<T> listMapBean(List<Map<String, Object>> list, Class<T> clazz) {
        List<T> beanList = new ArrayList<>();
        for (Map<String, Object> map : list) {
            T bean = mapToBean(map, clazz);
            beanList.add(bean);
        }
        return beanList;
    }





    /**
     * 手动分页list转page
     *
     * @param list     数据
     * @param pageNo   页码
     * @param pageSize 每页数据数量
     * @return
     */
    public static <T> Page<T> listToPage(List<T> list, Integer pageNo, Integer pageSize) {
        if (Objects.isNull(pageNo) || Objects.isNull(pageSize)) {
            return new Page<>();
        }
        List<T> resList = list.stream()
                .skip((pageNo - 1) * pageSize)
                .limit(pageSize)
                .collect(Collectors.toList());
        Page<T> resPage = new Page<>(pageNo, pageSize, list.size());
        resPage.setRecords(resList);
        return resPage;
    }
}
